﻿using ITSparta.Collections;
using ITSparta.MVVM;
using ITSparta.MVVM.Services;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;

namespace SPConfigDBReaderApp.ViewModels
{
    public class MainWindowViewModel : WindowViewModel
    {
        #region Fields

        private static MainWindowViewModel _current = null;
        private string _connectionString = @"Server=localhost;Database=SharePoint_Config_9fb07c17-4184-4e9a-ad37-7e386b59183c;Integrated Security=True;MultipleActiveResultSets=True";

        private Dictionary<Guid, ClassViewModel> _classes = null;
        private ClassViewModel _rootClass = null;
        private ClassViewModel _selectedClass = null;

        private Dictionary<Guid, ObjectViewModel> _objects = null;
        private ObjectViewModel _rootObject = null;
        private ObjectViewModel _selectedObject = null;

        private MTObservableCollection<ClassViewModel> _rootClasses = new MTObservableCollection<ClassViewModel>();
        private MTObservableCollection<ObjectViewModel> _rootObjects = new MTObservableCollection<ObjectViewModel>();

        #endregion

        #region Properties

        public static MainWindowViewModel Current { get { return _current; } }

        public string ConnectionString { get { return _connectionString; } set { _connectionString = value; OnPropertyChanged("ConnectionString"); } }

        public MTObservableCollection<ClassViewModel> RootClasses { get { return _rootClasses; } }
        public IEnumerable<ClassViewModel> Classes { get { return _classes != null ? _classes.Values.ToList() : null; } }
        public ClassViewModel RootClass { get { return _rootClass; } private set { _rootClass = value; OnPropertyChanged("RootClass"); } }
        public ClassViewModel SelectedClass { get { return _selectedClass; } set { _selectedClass = value; OnPropertyChanged("SelectedClass"); } }

        public MTObservableCollection<ObjectViewModel> RootObjects { get { return _rootObjects; } }
        public IEnumerable<ObjectViewModel> Objects { get { return _objects != null ? _objects.Values.ToList() : null; } }
        public ObjectViewModel RootObject { get { return _rootObject; } private set { _rootObject = value; OnPropertyChanged("RootObject"); } }
        public ObjectViewModel SelectedObject { get { return _selectedObject; } set { _selectedObject = value; OnPropertyChanged("SelectedObject"); } }

        public ICommand ConnectCommand { get; private set; }

        #endregion

        #region Constructor

        public MainWindowViewModel() : base("SharePoint Configuration Reader")
        {
            ConnectCommand = ServiceBaseInstances.CommandService.CreateCommand(ConnectCommandExecute, ConnectCommandCanExecute);
        }

        #endregion

        #region

        private SqlConnection CreateConnection()
        {
            var conn = new SqlConnection(_connectionString);
            conn.Open();
            return conn;
        }

        public bool TryGetClass(Guid id, out ClassViewModel cl)
        {
            return _classes.TryGetValue(id, out cl);
        }

        #endregion

        #region Command handlers

        protected virtual void ConnectCommandExecute(object sender)
        {
            try
            {
                _rootClasses.Clear();
                _rootObjects.Clear();

                _classes = new Dictionary<Guid, ClassViewModel>();
                _objects = new Dictionary<Guid, ObjectViewModel>();

                ClassViewModel rootClass = null;
                ObjectViewModel rootObject = null;

                using (var connection = CreateConnection())
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandType = System.Data.CommandType.Text;
                        command.CommandText = "SELECT * FROM [dbo].[Classes]";

                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                var c = new ClassViewModel(reader);
                                if (c.IsRoot)
                                    rootClass = c;
                                _classes.Add(c.Id, c);
                            }
                        }
                    }

                    using (var command = connection.CreateCommand())
                    {
                        command.CommandType = System.Data.CommandType.Text;
                        command.CommandText = "SELECT * FROM [dbo].[Objects]";

                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                var c = new ObjectViewModel(reader);
                                if (c.IsRoot)
                                    rootObject = c;
                                _objects.Add(c.Id, c);
                            }
                        }
                    }
                }

                foreach (var c in _classes.Values)
                    c.Init();

                foreach (var c in _objects.Values)
                    c.Init();

                OnPropertyChanged("Classes");
                OnPropertyChanged("Objects");

                RootClass = rootClass;
                RootObject = rootObject;

                _rootClasses.Add(rootClass);
                _rootObjects.Add(rootObject);
            }
            catch (Exception ex)
            {
                ServiceBaseInstances.DialogService.ShowMessageBox(this, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        protected virtual bool ConnectCommandCanExecute(object sender)
        {
            return !string.IsNullOrWhiteSpace(ConnectionString);
        }

        #endregion

        #region Static

        internal static void Init()
        {
            _current = new MainWindowViewModel();
        }

        internal static void Stop()
        {
            _current.Dispose();
            _current = null;
        }

        #endregion
    }
}